package com.jinlia.show.modules.system.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jinlia.show.modules.base.constant.EnableStatusEnum;
import com.jinlia.show.modules.base.system.entity.SysDept;
import com.jinlia.show.modules.base.model.form.DeptForm;
import com.jinlia.show.modules.base.model.po.SysDeptPO;
import com.jinlia.show.modules.base.model.query.DeptQuery;
import com.jinlia.show.modules.base.system.service.SysDeptMapperService;
import com.jinlia.show.modules.system.constant.SystemConstants;
import com.jinlia.show.modules.system.model.Option;
import com.jinlia.show.modules.system.service.ifc.ISysDeptService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class SysDeptService extends SysDeptMapperService implements ISysDeptService {
    @Override
    public List<SysDeptPO> listDepartments(DeptQuery queryParams) {
        // 查询参数
        List<SysDept> list = this.lambdaQuery()
                .like(StringUtils.hasLength(queryParams.getKeywords()), SysDept::getName, queryParams.getKeywords())
                .eq(queryParams.getStatus() != null, SysDept::getStatus, queryParams.getStatus())
                .orderByAsc(SysDept::getSort)
                .list();
        if (CollectionUtils.isEmpty(list)) {
            return Collections.EMPTY_LIST;
        }

        List<SysDeptPO> sysRoleVOList = list.stream().map((item) -> SysDeptPO.fromEntity(item)).collect(Collectors.toList());
        Map<Long, SysDeptPO> idVsSysRoleMap = sysRoleVOList.stream().collect(Collectors.toMap(i -> i.getId(), i2 -> i2));
        for (SysDeptPO sysRoleVO : sysRoleVOList) {
            if (!idVsSysRoleMap.containsKey(sysRoleVO.getParentId())) {
                continue;
            }
            SysDeptPO parentSysRole = idVsSysRoleMap.get(sysRoleVO.getParentId());
            if (Objects.isNull(parentSysRole.getChildren())) {
                parentSysRole.setChildren(new ArrayList<>());
            }
            parentSysRole.getChildren().add(sysRoleVO);
        }
        //获取根节点
        List<SysDeptPO> collect = sysRoleVOList.stream()
                .filter(i -> SystemConstants.ROOT_NODE_ID.equals(i.getParentId()))
                .collect(Collectors.toList());
        // 递归生成部门树形列表
        return collect;
    }

    @Override
    public List<Option> listDeptOptions() {
        List<SysDept> deptList = this.lambdaQuery()
                .eq(SysDept::getStatus, EnableStatusEnum.ENABLE.getValue())
                .select(SysDept::getId, SysDept::getParentId, SysDept::getName)
                .orderByAsc(SysDept::getSort)
                .list();
        List<Option> collect = deptList.stream().map((item) -> new Option(item.getId(), item.getName(), item.getParentId())).collect(Collectors.toList());

        Map<Object, Option> optionMap = collect.stream().collect(Collectors.toMap(i -> i.getValue(), i2 -> i2));
        for (Option sysRoleVO : collect) {
            if (!optionMap.containsKey(sysRoleVO.getParent())) {
                continue;
            }
            Option optionParent = optionMap.get(sysRoleVO.getParent());
            if (Objects.isNull(optionParent.getChildren())) {
                optionParent.setChildren(new ArrayList<>());
            }
            optionParent.getChildren().add(sysRoleVO);
        }
        //获取根节点
        List<Option> collectSysDeptVO = collect.stream().filter(i -> SystemConstants.ROOT_NODE_ID.equals(i.getParent())).collect(Collectors.toList());
        return collectSysDeptVO;
    }

    @Override
    public Long saveDept(DeptForm formData) {

        // 校验部门名称是否存在
        String name = formData.getName();
        long count = this.count(new LambdaQueryWrapper<SysDept>()
                .eq(SysDept::getName, name)
        );

        // form->entity
        SysDept entity = new SysDept();
        BeanUtils.copyProperties(formData, entity);
        // 生成部门路径(tree_path)，格式：父节点tree_path + , + 父节点ID，用于删除部门时级联删除子部门
        String treePath = generateDeptTreePath(formData.getParentId());
        entity.setTreePath(treePath);

        // 保存部门并返回部门ID
        boolean result = this.save(entity);

        return entity.getId();
    }

    @Override
    public Long updateDept(Long deptId, SysDeptPO formData) {
        // 校验部门名称是否存在
        String name = formData.getName();
        long count = this.count(new LambdaQueryWrapper<SysDept>()
                .eq(SysDept::getName, name)
                .ne(SysDept::getId, deptId)
        );

        // form->entity
        // form->entity
        SysDept entity = new SysDept();
        BeanUtils.copyProperties(formData, entity);
        entity.setId(deptId);

        // 生成部门路径(tree_path)，格式：父节点tree_path + , + 父节点ID，用于删除部门时级联删除子部门
        String treePath = generateDeptTreePath(formData.getParentId());
        entity.setTreePath(treePath);

        // 保存部门并返回部门ID
        boolean result = this.updateById(entity);

        return entity.getId();
    }

    @Override
    public boolean deleteByIds(String ids) {

        // 删除部门及子部门
        if (StringUtils.hasLength(ids)) {
            String[] menuIds = ids.split(",");
            for (String deptId : menuIds) {
                this.remove(new LambdaQueryWrapper<SysDept>()
                        .eq(SysDept::getId, deptId)
                        .or()
                        .apply("CONCAT (',',tree_path,',') LIKE CONCAT('%,',{0},',%')", deptId));
            }
        }
        return true;
    }

    @Override
    public SysDeptPO getDeptForm(Long deptId) {
        SysDept entity = this.getOne(new LambdaQueryWrapper<SysDept>()
                .eq(SysDept::getId, deptId)
                .select(
                        SysDept::getId,
                        SysDept::getName,
                        SysDept::getParentId,
                        SysDept::getStatus,
                        SysDept::getSort
                ));
        return SysDeptPO.fromEntity(entity);
    }

    /**
     * 部门路径生成
     *
     * @param parentId 父ID
     * @return 父节点路径以英文逗号(, )分割，eg: 1,2,3
     */
    private String generateDeptTreePath(Long parentId) {
        String treePath = null;
        if (SystemConstants.ROOT_NODE_ID.equals(parentId)) {
            treePath = String.valueOf(parentId);
        } else {
            SysDept parent = this.getById(parentId);
            if (parent != null) {
                treePath = parent.getTreePath() + "," + parent.getId();
            }
        }
        return treePath;
    }
}
